package cn.org.tpeach.nosql.controller;


import cn.org.tpeach.nosql.constant.PublicConstant;
import cn.org.tpeach.nosql.enums.RedisTreeType;
import cn.org.tpeach.nosql.framework.LarkFrame;
import cn.org.tpeach.nosql.framework.ServiceProxy;
import cn.org.tpeach.nosql.redis.bean.RedisConnectInfo;
import cn.org.tpeach.nosql.redis.bean.RedisTreeItem;
import cn.org.tpeach.nosql.redis.controller.BaseController;
import cn.org.tpeach.nosql.redis.controller.ResultRes;
import cn.org.tpeach.nosql.redis.service.IRedisConfigService;
import cn.org.tpeach.nosql.redis.service.IRedisConnectService;
import cn.org.tpeach.nosql.tools.StringUtils;
import cn.org.tpeach.nosql.view.JavaFxUtil;
import cn.org.tpeach.nosql.view.PasswordShowField;
import cn.org.tpeach.nosql.view.PasswordShowTextFiledSkin;
import io.lettuce.core.RedisURI;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ObservableList;
import javafx.event.Event;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import lombok.Getter;


import java.net.URL;
import java.util.ResourceBundle;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

@Getter
public class AddServerController implements Initializable {
    private final IRedisConnectService redisConnectService = ServiceProxy.getBeanProxy("redisConnectService", IRedisConnectService.class);
    private final IRedisConfigService redisConfigService = ServiceProxy.getBeanProxy("redisConfigService", IRedisConfigService.class);

    @FXML
    private GridPane serverMainInfoGridPane;
    @FXML
    private GridPane sshGridPane;
    @FXML
    private GridPane sslGridPane;
    @FXML
    private TextField serverMainInfoAddress;
    @FXML
    private TextField serverMainInfoName;

    private PasswordShowField serverMainInfoAuth;

    @FXML
    private TextField serverMainInfoPort;
    @FXML
    private CheckBox serverMainInfoClusterCheckBox;
    @FXML
    private CheckBox serverMainInfoSshCheckBox;
    @FXML
    private CheckBox serverMainInfoSslCheckBox;

    @FXML
    private CheckBox serverMainInfoShowAuthCheckBox;

    @FXML
    private TextField nameSpaceSepartorField;
    @FXML
    private TextField dbAmountField;
    @FXML
    private TextField timeOutField;

    private Dialog dialog;
    private RedisConnectInfo oldConnectInfo;
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        sshGridPane.setBorder(new Border(new BorderStroke(Color.rgb(186,186,186), BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)));
        sslGridPane.setBorder(new Border(new BorderStroke(Color.rgb(186,186,186), BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths.DEFAULT)));
        serverMainInfoAuth = new PasswordShowField();
        serverMainInfoAuth.setPromptText("连接密码");
        serverMainInfoGridPane.add(serverMainInfoAuth,1,2,3,1);

        serverMainInfoClusterCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> {
            serverMainInfoPort.setDisable(newValue);
            clusterListener(newValue);
        });
        serverMainInfoShowAuthCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> {
            serverMainInfoAuth.setShowPassword(newValue);
            serverMainInfoAuth.setText(serverMainInfoAuth.getText());
        });

        nameSpaceSepartorField.setText(PublicConstant.NAMESPACE_SPLIT);
        dbAmountField.setText(RedisConnectInfo.DEFAULT_DBAMOUNT+"");
        timeOutField.setText(RedisURI.DEFAULT_TIMEOUT+"");
        sslGridPane.setVisible(false);
        serverMainInfoSslCheckBox.setVisible(false);
        serverMainInfoSshCheckBox.setOnMouseClicked(event -> {
            JavaFxUtil.showMessageErrorDialog(null,null,"暂不支持");
            serverMainInfoSshCheckBox.setSelected(false);

        });

    }



    public void initialize(Dialog dialog, RedisConnectInfo oldConnectInfo, Button configButton, Button testButton, TreeView redisTree, AtomicBoolean canClose){
        this.dialog = dialog;
        this.oldConnectInfo = oldConnectInfo;
        configButton.setDisable(true);
        testButton.setDisable(true);
        serverMainInfoName.textProperty().addListener((observable, oldValue, newValue) ->  disableButton(configButton,testButton));
        serverMainInfoAddress.textProperty().addListener((observable, oldValue, newValue) ->  disableButton(configButton,testButton));
        serverMainInfoPort.textProperty().addListener((observable, oldValue, newValue) ->  disableButton(configButton,testButton));
        serverMainInfoAuth.textProperty().addListener((observable, oldValue, newValue) ->  disableButton(configButton,testButton));
        serverMainInfoClusterCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> disableButton(configButton,testButton));
        initEdit(oldConnectInfo);

        testButton.setStyle("-fx-background-color:gray;");
        //测试连接
        testButton.setOnAction(event -> testConnect(testButton));

        configButton.setOnAction(event -> submit(redisTree,canClose));

    }

    public void submit( TreeView<RedisTreeItem> redisTree,AtomicBoolean canClose){
        RedisConnectInfo connectInfo = getConnectInfo();
        ResultRes<RedisConnectInfo> res;
        if (oldConnectInfo == null) {
            res = BaseController.dispatcher(() -> redisConfigService.addRedisConfig(connectInfo));
        } else {
            res = BaseController.dispatcher(() -> redisConfigService.updateRedisConfig(connectInfo));
        }
        if (res.isRet()) {
            canClose.set(true);
            dialog.close();
            //刷新树
            if(oldConnectInfo == null){
                redisTree.getRoot().getChildren().add(new TreeItem<>(RedisTreeItem.builder()
                        .id(connectInfo.getId())
                        .name(connectInfo.getName())
                        .originName(connectInfo.getName())
                        .type(RedisTreeType.SERVER)
                        .build()));
            }else{
                ObservableList<TreeItem<RedisTreeItem>> children = redisTree.getRoot().getChildren();
                TreeItem<RedisTreeItem> treeItem = null;
                for (TreeItem<RedisTreeItem> child : children) {
                    if(StringUtils.equals(child.getValue().getId(),oldConnectInfo.getId())){
                        treeItem = child;
                        break;
                    }
                }
                if(treeItem != null){
                    RedisTreeItem value = treeItem.getValue();
                    value.setName(connectInfo.getName());
                    value.setOriginName(connectInfo.getName());
                    Event.fireEvent(treeItem, new TreeItem.TreeModificationEvent<>(TreeItem.valueChangedEvent(), treeItem, treeItem.getValue()));
                }
            }
            RedisApplication.mainController.hasServerData();
        }else{
            canClose.set(false);
            JavaFxUtil.showMessageErrorDialog(null,null,res.getMsg());
        }
    }

    private void disableButton(Button configButton,Button testButton){
        configButton.setDisable(this.checkRedisKeyInfo());
        testButton.setDisable(this.checkRedisKeyInfo());
    }


    private void testConnect(Button testButton){
        testButton.setText("连接中");
        LarkFrame.executorService.execute(()->{
            try {
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Platform.runLater(() ->{
                RedisConnectInfo connectInfo = getConnectInfo();
                if(connectInfo == null){
                    testButton.setStyle("-fx-background-color:red;");
                }else{
                    ResultRes<Boolean> res = BaseController.dispatcher(() -> redisConnectService.connectTest(connectInfo));
                    if(res.isRet()){
                        testButton.setStyle("-fx-background-color:#84B547;");
                        testButton.setText("成功");
                    }else{
                        JavaFxUtil.showMessageErrorDialog(null,null,res.getMsg());
                        testButton.setStyle("-fx-background-color:red;");
                        testButton.setText("重试");
                    }
                }
            });
        });
    }


    private void initEdit(RedisConnectInfo connectInfo){
        if(connectInfo != null){
            int structure = connectInfo.getStructure();
            if(structure == 1 ){
                serverMainInfoClusterCheckBox.setSelected(true);
            }
            serverMainInfoName.setText(connectInfo.getName());
            serverMainInfoAddress.setText(connectInfo.getHost());
            serverMainInfoPort.setText(connectInfo.getPort()+"");
            serverMainInfoAuth.setText(connectInfo.getAuth());

            nameSpaceSepartorField.setText(connectInfo.getNameSpaceSepartor());
            timeOutField.setText(connectInfo.getTimeout()+"");
            dbAmountField.setText(connectInfo.getDbAmount()+"");
        }
    }

    public void clusterListener(boolean isCluster){
        serverMainInfoGridPane.getChildren().remove(serverMainInfoAddress);
        if(isCluster){
            serverMainInfoAddress.setPromptText("ip1:port1,ip2:port2,ip3:port3...(英文逗号分隔)");
            serverMainInfoGridPane.add(serverMainInfoAddress,1,1,7,1);
        }else{
            serverMainInfoAddress.setPromptText("连接地址");
            serverMainInfoGridPane.add(serverMainInfoAddress,1,1,4,1);
        }
    }

    public  boolean checkRedisKeyInfo(){
        CheckBox serverMainInfoClusterCheckBox = this.getServerMainInfoClusterCheckBox();
        TextField serverMainInfoName = this.getServerMainInfoName();
        TextField serverMainInfoAddress = this.getServerMainInfoAddress();
        TextField serverMainInfoPort = this.getServerMainInfoPort();
        if(StringUtils.isBlank(serverMainInfoName.getText())){
            return true;
        }
        if(StringUtils.isBlank(serverMainInfoAddress.getText())){
            return true;
        }
        if(!serverMainInfoClusterCheckBox.isSelected() && StringUtils.isBlank(serverMainInfoPort.getText())){
            return true;
        }
        return false;

    }


    private  RedisConnectInfo getConnectInfo(){

        int structure = serverMainInfoClusterCheckBox.isSelected() ? 1 : 0;
        int port = -1;
        if(!serverMainInfoClusterCheckBox.isSelected()){
            try {
                port = Integer.valueOf(serverMainInfoPort.getText());
            } catch (NumberFormatException ex) {
                JavaFxUtil.showMessageErrorDialog(LarkFrame.primaryStage,null,"请输入正确的端口");
                dialog.show();
                return null;
            }
        }
        RedisConnectInfo connectInfo = new RedisConnectInfo();
        if(oldConnectInfo != null){
            connectInfo.setId(oldConnectInfo.getId());
        }
        connectInfo.setName(serverMainInfoName.getText());
        connectInfo.setAuth(serverMainInfoAuth.getText());
        connectInfo.setHost(serverMainInfoAddress.getText());
        connectInfo.setPort(port);
        connectInfo.setStructure(structure);
        if(StringUtils.isNotBlank(timeOutField.getText())){
            try{
                connectInfo.setTimeout(Long.parseLong(timeOutField.getText()));
            }catch (Exception e){}
        }
        if(StringUtils.isNotBlank(nameSpaceSepartorField.getText())){
            connectInfo.setNameSpaceSepartor(nameSpaceSepartorField.getText());
        }
        if(StringUtils.isNotBlank(dbAmountField.getText())){
            try{
                connectInfo.setDbAmount(Integer.parseInt(dbAmountField.getText()));
            }catch (Exception e){}
        }
        return connectInfo;
    }


}
